home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.src.lzh / input / c7decode.c < prev    next >
C/C++ Source or Header  |  1980-01-01  |  3KB  |  186 lines

  1. #include <stdio.h>
  2.  
  3. /*
  4.  * This program is the inverse of encode
  5.  *
  6.  * It collects runs of 12 characters, combines pairs of those
  7.  * to form 6 13 bit numbers, extracts the top bit of each of
  8.  * those to make a 13th 6 bit character, and splits each of
  9.  * the remaining 6 12 bit numbers to form 12 6 bit ones.
  10.  *
  11.  * The strings of 6 bit numbers are collected into groups of
  12.  * 4 and converted into 3 8 bit characters.
  13.  *
  14.  * Now all that would be trivial, if we didn't need to worry
  15.  * about ending all this correctly.  About 1/2 of the following
  16.  * program wouldn't be here if the ending didn't matter....
  17.  */
  18.  
  19. /*
  20.  * the following pair of characters can never occur as a pair
  21.  * in legal input (since (90 * 91 + 90) > 2^13) - they are
  22.  * noticed at the beginning of a 12 char block, and serve to
  23.  * indicate that this block is the terminator.  The character
  24.  * immediately following is the (expanded) terminator length.
  25.  */
  26. #define    ENDMARK1    ((90*91 + 90) / 91)
  27. #define    ENDMARK2    ((90*91 + 90) % 91)
  28.  
  29. int errcnt = 0;
  30.  
  31. main()
  32. {
  33.     register c;
  34.     register char *p;
  35.     register i;
  36.     register first = 1;
  37.     register cnt = 0;
  38.     char b12[12];
  39.     char c12[12];
  40.  
  41.     p = b12;
  42.     i = 12;
  43.  
  44.     while ((c = getchar()) != EOF) {
  45.         if (c < ' ' || c >= (' ' + 91)) {
  46.             if (errcnt++ == 0)
  47.                 fprintf(stderr, "c7decode: Bad data\n");
  48.             continue;
  49.         }
  50.         if (i == 10 && p[-1] == ENDMARK1 && p[-2] == ENDMARK2) {
  51.             cnt = c - ' ';
  52.             i = 12;
  53.             p -= 2;
  54.             continue;
  55.         }
  56.         *p++ = c - ' ';
  57.         if (--i == 0) {
  58.             if (p == &b12[12]) {
  59.                 if (!first)
  60.                     pack12(c12, 12, 0);
  61.                 else
  62.                     first = 0;
  63.                 p = c12;
  64.             } else {
  65.                 pack12(b12, 12, 0);
  66.                 p = b12;
  67.             }
  68.             i = 12;
  69.         }
  70.     }
  71.  
  72.     if (p >= &b12[0] && p < &b12[12]) {
  73.         if (!first)
  74.             pack12(c12, 12, i == 12 ? cnt : 0);
  75.     } else
  76.         pack12(b12, 12, i == 12 ? cnt : 0);
  77.  
  78.     if (i != 12) {
  79.         if (p >= &b12[0] && p < &b12[12])
  80.             pack12(b12, 12-i, cnt);
  81.         else
  82.             pack12(c12, 12-i, cnt);
  83.     }
  84.  
  85.     exit((errcnt > 0) ? 1 : 0);
  86. }
  87.  
  88. static char b4[4];
  89. static int cnt = 0;
  90.  
  91. pack12(p, n, last)
  92.     register char *p;
  93.     register n;
  94.     int last;
  95. {
  96.     register i;
  97.     register char *q;
  98.     char b13[13];
  99.  
  100.     {
  101.         register c;
  102.         register c13;
  103.  
  104.         q = b13;
  105.         c13 = 0;
  106.  
  107.         for (i = 0; i < n; i += 2) {
  108.             c = *p++ * 91;
  109.             c += *p++;
  110.             c13 <<= 1;
  111.             if (c & (1 << 12))
  112.                 c13 |= 1;
  113.             *q++ = (c >> 6) & 0x3f;
  114.             *q++ = c & 0x3f;
  115.         }
  116.         *q++ = c13;
  117.         if (last)
  118.             q = &b13[last];
  119.     }
  120.  
  121.     p = b13;
  122.     n = q - p;
  123.     i = cnt;
  124.     q = &b4[cnt];
  125.  
  126.     while (--n > 0) {
  127.         *q++ = *p++;
  128.         if (++i == 4) {
  129.             char b3[3];
  130.             register char *b = b4;
  131.  
  132.             /* inline expansion of pack6bit, to save calls ... */
  133.  
  134.             q = b3;
  135.             *q++ = (b[0] << 2) | ((b[1] >> 4) & 0x3);
  136.             *q++ = (b[1] << 4) | ((b[2] >> 2) & 0xf);
  137.             *q = (b[2] << 6) | (b[3] & 0x3f);
  138.  
  139.             q = b3;
  140.             while (--i > 0)
  141.                 putchar(*q++);
  142.  
  143.             q = b4;
  144.         }
  145.     }
  146.  
  147.     *q++ = *p++;    /* the last octet */
  148.     ++i;
  149.  
  150.     if (last || i == 4) {
  151.         pack6bit(b4, i, last);
  152.         i = 0;
  153.     }
  154.  
  155.     cnt = i;
  156. }
  157.  
  158. pack6bit(p, n, last)
  159.     register char *p;
  160.     register int n;
  161.     int last;
  162. {
  163.     register char *q;
  164.     register i = 3;
  165.     char b3[3];
  166.  
  167.     if (last) {
  168.         i = p[n-1];
  169.         if (i >= 3) {
  170.             fprintf(stderr, "c7decode: Badly encoded file\n");
  171.             errcnt++;
  172.             i = 3;        /* do the best we can */
  173.         }
  174.     }
  175.  
  176.     q = b3;
  177.     *q++ = (p[0] << 2) | ((p[1] >> 4) & 0x3);
  178.     *q++ = (p[1] << 4) | ((p[2] >> 2) & 0xf);
  179.     *q = (p[2] << 6) | (p[3] & 0x3f);
  180.  
  181.     q = b3;
  182.  
  183.     while (--i >= 0)
  184.         putchar(*q++);
  185. }
  186.